package org.com.yz.dubbo.service.impl;

import cn.hutool.core.date.DateTime;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.com.yz.common.config.ConfigureTest;
import org.com.yz.common.config.IRequestService;
import org.com.yz.common.constant.PayConstant;
import org.com.yz.common.util.*;
import org.com.yz.dal.dao.mapper.AuthenticationDetailMapper;
import org.com.yz.dal.dao.mapper.BankCardMapper;
import org.com.yz.dal.dao.mapper.MchAccntMapper;
import org.com.yz.dal.dao.mapper.WithDrawInfoMapper;
import org.com.yz.dal.dao.model.*;
import org.com.yz.dubbo.service.BaseService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.*;

/**
 * Created by lsk on 2018-7-12.
 */
@Component
public class AsyncTask  {
    private static Logger log = LoggerFactory.getLogger(AsyncTask.class);

    @Autowired
    private AuthenticationDetailMapper authenticationDetailMapper;

    @Autowired
    private BankCardMapper bankCardMapper;

    @Autowired
    private WithDrawInfoMapper withDrawInfoMapper;

    @Autowired
    private BaseService baseService;

    @Autowired
    private MchAccntMapper mchAccntMapper;





    /**
     * 绑定对公账户小额异步查询（打款后异步查询状态，成功或失败异步通知，并且更改对应状态）
     * *** 对私用定时任务查询收付直通车
     * @param mchAccntNo
     * @param withdrawPay
     * @param mchNo
     * @param cardNo
     * @param url
     * @throws Exception
     */
    @Async
    public void withDrawPayQuery(String mchAccntNo,WithdrawPay withdrawPay,
                                 String mchNo,String cardNo,String url, BankCard bankCard) throws Exception{
        boolean flag = false;
        String trunId = withdrawPay.getTrunId();
        int queryNo = 1; //第5次查询每隔10秒
        while (withdrawPay!=null && "PENDING".equals(withdrawPay.getXferprccode())){
            if (queryNo > 4){
                Thread.sleep(1000*10); //休眠10秒钟
            }else {
                Thread.sleep(1000*60); //线程休眠1分钟
            }
            //查询转账接口
            queryNo ++ ;
            withdrawPay = WithdrawPayUtil.withdrawPayQuery(mchNo,trunId,"1");//根据订单号（orderNo），异步查询转账
        }
        HashMap<String, String> params = new HashMap<String, String>();
        params.put("mch_accnt_no", mchAccntNo);
        params.put("card_no", cardNo);
        AuthenticationDetail authenticationDetail = new AuthenticationDetail();//鉴权明细信息
//        BankCard bankCard = new BankCard();
        if("FAIL".equals(withdrawPay.getXferprccode())){ //失败
            params.put("status", "2");
            params.put("message", withdrawPay.getMessage());
            bankCard.setTracNo(trunId);
            bankCardMapper.deleteTracNo(bankCard);//删除银行卡信息

            authenticationDetail.setOrderNo(trunId);
            authenticationDetail.setMchNo(mchNo);
            authenticationDetailMapper.delete(authenticationDetail);//删除鉴权明细信息

            flag = true;
        }else if("PAYOUT".equals(withdrawPay.getXferprccode())){ //成功
            params.put("status", "1");
            params.put("message", withdrawPay.getMessage());

            //**1.插入对公账户信息,对公账户绑定状态为待认定
            insertBankCard(bankCard, mchNo, withdrawPay.getTrunId(), "0", "to_handle", "打款成功", Integer.parseInt(AmountUtil.convertDollar2Cent(withdrawPay.getTrnamt())));
            //**2.记录鉴权明细
            insertAuthenticationDetail(bankCard, mchNo, withdrawPay.getTrunId(), "打款成功", "to_handle", "0", String.valueOf(AmountUtil.convertDollar2Cent(withdrawPay.getTrnamt())));

            /*authenticationDetail.setStatus("success");//状态
            authenticationDetail.setRemark("打款成功");
            authenticationDetail.setMchNo(mchNo);//商户号
            authenticationDetail.setOrderNo(trunId);//订单号/请求追踪号
            authenticationDetail.setMchAccntNo(mchAccntNo);
            authenticationDetailMapper.updateAuthenticationDetail(authenticationDetail);//更新鉴权明细信息*/
            flag = true;
        }
        Map<String,Object> dataMap = new HashMap<>();
        dataMap.put("biz_content",JSON.toJSONString(params));
        dataMap.put("mch_no",mchNo);
        dataMap.put("out_trans_no",MySeq.getNotifyTrans());
        dataMap.put("biz_type","mchsub.bind.notify");
        dataMap.put("sign_type","MD5");
        dataMap.put("timestamp",DateUtil.getCurrentDate());

        Map<String,String> resultMap = new HashMap<>();

        String token = CacheUtil.me().getMd5Token(mchNo);
        String md5Data = JSONObject.toJSONString(dataMap)+"&"+dataMap.get("timestamp")+token;
        log.info("签名原串为："+md5Data);
        String sign = PayDigestUtil.md5(md5Data,"UTF-8");
        resultMap.put("data",JSON.toJSONString(dataMap));
        resultMap.put("sign",sign);

        String json = null;
        log.info("请求的地址为："+url);
        if(flag){
            json = txn(url,resultMap,"");
            log.info("接收到的数据为："+json);
            int queryNos = 1; //第5次查询每隔10秒
            while (!"success".equals(json)){
                log.info("对方没有确认！");
                if (queryNos > 5){
                    return;
                }else {
                    Thread.sleep(1000*30); //线程休眠1分钟
                }
                //查询转账接口
                queryNos ++ ;
                json = txn(url,resultMap,"");
                log.info("第"+queryNos+"次请求接收到的数据为："+json);
            }
        }
    }

    /**
     * 异步查询转账状态
     * @param mchAccntNo
     * @param withdrawPay
     * @param mchNo
     * @param cardNo
     * @param url
     * @param bankCard
     * @throws Exception
     */
    @Async
    public void queryTransferStatus(String mchAccntNo, WithdrawPay withdrawPay, String mchNo, String cardNo,String url,
                                    BankCard bankCard) throws Exception{
        boolean flag = false;
        String trunId = withdrawPay.getTrunId();
        int queryNo = 1; //第5次查询每隔10秒
        while (withdrawPay != null && "PENDING".equals(withdrawPay.getXferprccode())){
            if (queryNo > 4){
                Thread.sleep(1000*10); //休眠10秒钟
            }else {
                Thread.sleep(1000*60); //线程休眠1分钟
            }
            //查询转账接口
            queryNo ++ ;
            withdrawPay = WithdrawPayUtil.withdrawPayQuery(mchNo, trunId,"1");//根据订单号（orderNo），异步查询转账
        }

        Map<String, String> params = new HashMap<>();
        params.put("mch_accnt_no", mchAccntNo);
        params.put("card_no", cardNo);
        AuthenticationDetail authenticationDetail = new AuthenticationDetail(); //鉴权明细信息
        if("FAIL".equals(withdrawPay.getXferprccode())){ //失败
            params.put("status", "2");
            params.put("message", withdrawPay.getMessage());
            bankCard.setTracNo(trunId);
            bankCardMapper.deleteTracNo(bankCard);//删除银行卡信息

            authenticationDetail.setOrderNo(trunId);
            authenticationDetail.setMchNo(mchNo);
            authenticationDetailMapper.delete(authenticationDetail);//删除鉴权明细信息

            flag = true;
        }else if("PAYOUT".equals(withdrawPay.getXferprccode())){ //成功
            params.put("status", "1");
            params.put("message", withdrawPay.getMessage());

            //插入对公账户信息,对公账户绑定状态为待认定
//            insertBankCard(bankCard, mchNo, withdrawPay.getTrunId(), "0", "to_handle", "打款成功", Integer.parseInt(AmountUtil.convertDollar2Cent(withdrawPay.getTrnamt())));
            //记录鉴权明细
//            insertAuthenticationDetail(bankCard, mchNo, withdrawPay.getTrunId(), "打款成功", "to_handle", "0", String.valueOf(AmountUtil.convertDollar2Cent(withdrawPay.getTrnamt())));

            //更新对公账户状态
            bankCard.setStatus("to_handle");
            bankCard.setRemark("打款成功");
            bankCard.setMchNo(mchNo);
            bankCard.setMchAccntNo(mchAccntNo);
            bankCard.setOrderNo(trunId);
            bankCardMapper.undateNoSuess(bankCard);

            //更新鉴权明细状态
            authenticationDetail.setStatus("success");
            authenticationDetail.setRemark("打款成功");
            authenticationDetail.setMchNo(mchNo);
            authenticationDetail.setOrderNo(trunId);
            authenticationDetail.setMchAccntNo(mchAccntNo);
            authenticationDetailMapper.updateAuthenticationDetail(authenticationDetail);
            flag = true;
        }

        //异步通知转账结果
        notifyTransferResult(flag, params, mchNo, url);
    }

    /**
     * 异步通知转账结果
     * @param flag
     * @param params
     * @param mchNo
     * @param url
     */
    public void notifyTransferResult(boolean flag, Map<String, String> params, String mchNo, String url){
        Map<String,Object> dataMap = new HashMap<>();
        dataMap.put("biz_content", JSON.toJSONString(params));
        dataMap.put("mch_no", mchNo);
        dataMap.put("out_trans_no", MySeq.getNotifyTrans());
        dataMap.put("biz_type", "mchsub.bind.notify");
        dataMap.put("sign_type", "MD5");
        dataMap.put("timestamp", DateUtil.getCurrentDate());

        String token = CacheUtil.me().getMd5Token(mchNo);
        String md5Data = JSONObject.toJSONString(dataMap) + "&" + dataMap.get("timestamp") + token;
        log.info("签名原串为：{}", md5Data);
        String sign = PayDigestUtil.md5(md5Data,"UTF-8");

        Map<String,String> resultMap = new HashMap<>();
        resultMap.put("data", JSON.toJSONString(dataMap));
        resultMap.put("sign", sign);

        String json = null;
        log.info("请求的地址为：{}", url);
        if(flag){
            json = txn(url, resultMap, "");
            log.info("接收到的数据为：{}", json);
            int queryNos = 1;
            while (!"success".equals(json)){
                log.info("对方没有确认！");
                if (queryNos > 5){
                    return;
                }else {
                    try {
                        Thread.sleep(1000*30);
                    }catch (InterruptedException e){
                        log.error("休眠异常");
                    }
                }
                queryNos ++ ;
                json = txn(url,resultMap,"");
                log.info("第{}次请求接收到的数据为：{}",queryNos, json);
            }
        }
    }

    public Integer insertBankCard(BankCard card, String mchNo, String orderNo, String type, String status, String remark, int amt) {
        //插入对公账户信息,对公账户绑定状态为待认定
        card.setStatus(status);
        card.setRemark(remark);
        card.setTracNo(orderNo);
        card.setCreateTime(new Date());
        card.setUpdateTime(new Date());
        card.setCardAccntType(type);
        card.setMchNo(mchNo);
        card.setVerifyPhoneCode(String.valueOf(amt));
        return bankCardMapper.insert(card);
    }



    /**
     * 记录鉴权明细
     *
     * @param bankCard 银行卡信息
     * @param mchNo    商户号
     * @param tracNo   订单号
     * @param remark   备注
     * @param status   认证状态
     * @param type     银行卡账户类型  0对公 1对私
     */
    private void insertAuthenticationDetail(BankCard bankCard, String mchNo, String tracNo, String remark, String status, String type, String fee) {
        // 记录鉴权明细
        AuthenticationDetail authenticationDetail = new AuthenticationDetail();
        //卡号
        authenticationDetail.setCardNo(bankCard.getCardNo());
        //子商户号
        authenticationDetail.setMchAccntNo(bankCard.getMchAccntNo());
        //商户号
        authenticationDetail.setMchNo(mchNo);
        //订单号/系统追踪号
        authenticationDetail.setOrderNo(tracNo);
        //鉴权类型 0对公 1对私
        authenticationDetail.setAuthenticationType(type);
        //鉴权时间
        authenticationDetail.setAuthenticationTime(new Date());
        //订单号（交易流水号）
        authenticationDetail.setOrderNo(bankCard.getTracNo());
        //持卡人姓名
        authenticationDetail.setUserName(bankCard.getUserName());
        //鉴权状态
        authenticationDetail.setStatus(status);
        //备注信息
        authenticationDetail.setRemark(remark);
        //创建时间
        authenticationDetail.setCreateTime(new Date());

        authenticationDetail.setFee(fee);
        authenticationDetailMapper.insert(authenticationDetail);
    }

    /**
     *超级网银--提现-异步查询(超级网银在提现后异步查询，成功或失败异步通知)
     * @param mchNo
     * @param mchAccntNo
     * @param withdrawPay
     * @throws Exception
     */
    @Async
    public void withDrawPayQueryByYqzl(String trunId,String mchAccntNo,WithdrawPay withdrawPay,
                                 String mchNo,String cardNo,String url) throws Exception {
        boolean flag = false;
        int queryNo = 1; //第5次查询每隔10秒
        while ("PENDING".equals(withdrawPay.getXferprccode())) {
            if (queryNo > 4) {
                Thread.sleep(1000 * 10); //休眠10秒钟
            } else {
                Thread.sleep(1000 * 60); //线程休眠1分钟
            }
            //查询转账接口
            queryNo++;
            withdrawPay = WithdrawPayUtil.withdrawPayQuery(mchNo, withdrawPay.getTrunId(), "0");//根据订单号（orderNo），异步查询转账 accnType 1代表 一般户
        }

//        url="http://127.0.0.1:3020/api/te.htm";
        HashMap<String, String> params = new HashMap<String, String>();
        params.put("mch_accnt_no", mchAccntNo);
        params.put("card_no", cardNo);
        if ("FAIL".equals(withdrawPay.getXferprccode())) { //失败
            params.put("status", "2");
            params.put("message", withdrawPay.getMessage());
            WithDrawInfo withdrawInfo = new WithDrawInfo();
            withdrawInfo.setOrderNo(trunId);
            withdrawInfo.setMchNo(mchNo);
            List<WithDrawInfo>withDrawInfoList =  withDrawInfoMapper.select(withdrawInfo);

            WithDrawInfo withDrawInfo = new WithDrawInfo();
            withDrawInfo.setMchNo(mchNo);//商户号
            withDrawInfo.setStatus("2");
            withDrawInfo.setOrderNo(trunId);//订单号
            withDrawInfo.setRemark(withdrawPay.getMessage());
            withDrawInfo.setUpdateTime(cn.hutool.core.date.DateUtil.now());//提现时间
            withDrawInfoMapper.updateWithDrawInfo(withDrawInfo);
            
            if(withDrawInfoList.size()>0 && withDrawInfoList.get(0)!=null){
                withDrawBackInfo(withDrawInfoList.get(0));
            }
            flag =true;
        } else if ("PAYOUT".equals(withdrawPay.getXferprccode())) { //成功
            params.put("status", "1");
            params.put("message", withdrawPay.getMessage());
            WithDrawInfo withDrawInfo = new WithDrawInfo();
            withDrawInfo.setMchNo(mchNo);//商户号
            withDrawInfo.setStatus("1");
            withDrawInfo.setOrderNo(trunId);//订单号
            withDrawInfo.setRemark(withdrawPay.getMessage());
            withDrawInfo.setUpdateTime(cn.hutool.core.date.DateUtil.now());//提现时间
            withDrawInfoMapper.updateWithDrawInfo(withDrawInfo);
            flag =true;
        }
        params.put("order_no", trunId);
        params.put("mch_accnt_no", mchAccntNo);
        params.put("amount",withdrawPay.getTrnamt());

        Map<String,Object> dataMap = new HashMap<>();
        dataMap.put("biz_content",JSON.toJSONString(params));
        dataMap.put("mch_no",mchNo);
        dataMap.put("out_trans_no","1111");
        dataMap.put("biz_type","mchaccnt.withdraw.notify");
        dataMap.put("sign_type","MD5");
        dataMap.put("timestamp", org.com.yz.common.util.DateUtil.getCurrentDate());

        Map<String,String> resultMap = new HashMap<>();

        String token = CacheUtil.me().getMd5Token(mchNo);
        String md5Data = JSONObject.toJSONString(dataMap)+"&"+dataMap.get("timestamp")+token;
        log.info("签名原串为："+md5Data);
        String sign = PayDigestUtil.md5(md5Data,"UTF-8");

        resultMap.put("data",JSON.toJSONString(dataMap));
        resultMap.put("sign",sign);
        log.info("请求的地址为："+url);
        String json = null;
        if(flag){
            json = txn(url,resultMap,"");
            log.info("接收到的数据为："+json);
            int queryNos = 1; //第5次查询每隔10秒
            while (!"success".equals(json)){
                log.info("对方没有确认！");
                if (queryNos > 5){
                    return;
                }else {
                    Thread.sleep(1000*30); //线程休眠1分钟
                }
                //查询转账接口
                queryNos ++ ;
                json = txn(url,resultMap,"");
                log.info("第"+queryNos+"次请求接收到的数据为："+json);
            }
        }
    }

    /**
     * 普通网银--提现结果异步通知（普通网银在定时任务里跑）
     * @param withDrawInfo
     * @param url
     * @param status
     * @param message
     * @throws InterruptedException
     */
    @Async
    public void withDrawNotify(WithDrawInfo withDrawInfo, String url, String status, String message) throws InterruptedException {

        String mchNo = withDrawInfo.getMchNo();
        //url="http://127.0.0.1:3020/api/te.htm";
        HashMap<String, String> params = new HashMap<String, String>();
        params.put("order_no", withDrawInfo.getOrderNo());
        params.put("mch_accnt_no", withDrawInfo.getMchAccntNo());
        params.put("status",status);
        params.put("message",message);

        Map<String,Object> dataMap = new HashMap<>();
        dataMap.put("biz_content",JSON.toJSONString(params));
        dataMap.put("mch_no",mchNo);
        dataMap.put("out_trans_no","1111");
        dataMap.put("biz_type","mchaccnt.withdraw.notify");
        dataMap.put("sign_type","MD5");
        dataMap.put("timestamp", org.com.yz.common.util.DateUtil.getCurrentDate());

        Map<String,String> resultMap = new HashMap<>();

        String token = CacheUtil.me().getMd5Token(mchNo);
        String md5Data = JSONObject.toJSONString(dataMap)+"&"+dataMap.get("timestamp")+token;
        log.info("签名原串为："+md5Data);
        String sign = PayDigestUtil.md5(md5Data,"UTF-8");

        resultMap.put("data",JSON.toJSONString(dataMap));
        resultMap.put("sign",sign);
        log.info("请求的地址为："+url);
        String json = null;
        json = txn(url,resultMap,"");
        log.info("接收到的数据为："+json);
        int queryNos = 1; //第5次查询每隔10秒
        while (!"success".equals(json)){
            log.info("对方没有确认！");
            if (queryNos > 5){
                return;
            }else {
                Thread.sleep(5000); //线程休眠1分钟
            }
            //查询转账接口
            queryNos ++ ;
            json = txn(url,resultMap,"");
            log.info("第"+queryNos+"次请求接收到的数据为："+json);
        }
    }


    /**
     * 发送http请求
     * @param url
     * @param params
     * @param mchNo
     * @return
     */
    public  String txn(String url, Map<String, String> params,String mchNo) {
        String json = null;
        try {
            IRequestService requestor = IRequestService.getInstance();
            json = (String) requestor.sendPost(url, params);
        } catch (IOException e) {
            json = ConfigureTest.TXN_ERROR_RESULT;
        } catch (Exception e) {
            json = ConfigureTest.SYS_ERROR_RESULT;
        }
        return json;
    }

    public  void withDrawBackInfo(WithDrawInfo withDrawInfo){
        Map accntMap = baseService.selectAllAccntInfo(withDrawInfo.getMchNo(),withDrawInfo.getMchAccntNo(),withDrawInfo.getOrderNo());
        String mchNo = withDrawInfo.getMchNo();

        MchAccnt withDrawAccnt = (MchAccnt) accntMap.get("withDraw");//提现账户
        MchAccnt depositoryAccnt = (MchAccnt) accntMap.get("depository");//存管户账户信息
        Long beforeWithDrawAmt = withDrawAccnt.getRemainAmt();//提现账户余额（交易前）
        MchAccnt prepayAccnt  = (MchAccnt) accntMap.get("prepay");//准备金
        Long beforePrepayAmt = prepayAccnt.getRemainAmt();
        HisAccntOnway2 onway2Accnt = (HisAccntOnway2)  accntMap.get("onway2");//在途2
        MchAccnt countAmtAccnt = (MchAccnt) accntMap.get("countamt");//商户可用余额总
        String mchAccntNo = withDrawInfo.getMchAccntNo();//子商户号
        String orderNo = withDrawInfo.getOrderNo();//订单号
        Long amt = withDrawInfo.getTransAmt();//提现金额

        //根据订单号查询  准备金余额明细、在途2余额明细

        HisAccntPrepay hisAccntPrepay = new HisAccntPrepay();
        hisAccntPrepay.setMchNo(mchNo);
        hisAccntPrepay.setOrderNo(orderNo);
        List<HisAccntPrepay> hisAccntPrepayInfoList = baseService.selectHisAccntPrepayList(hisAccntPrepay);//准备金明细
        Long prepayAmt = 0L,prepayAmt2 =0L;
        if (ToolUtil.isNotEmpty(hisAccntPrepayInfoList)) {
            if(hisAccntPrepayInfoList.size()>1){
                if("withdraw".equals(hisAccntPrepayInfoList.get(0).getEvent())){
                    prepayAmt = hisAccntPrepayInfoList.get(0).getEventAmt(); //记录的扣除准备金额
                    prepayAmt2 = hisAccntPrepayInfoList.get(1).getEventAmt(); //记录的扣除准备金额2
                }else{
                    prepayAmt2 = hisAccntPrepayInfoList.get(0).getEventAmt(); //记录的扣除准备金额
                    prepayAmt = hisAccntPrepayInfoList.get(1).getEventAmt(); //记录的扣除准备金额2
                }
            }else{
                prepayAmt = hisAccntPrepayInfoList.get(0).getEventAmt();
            }
        }

        HisAccntOnway2 hisAccntOnway2 = new HisAccntOnway2();
        hisAccntOnway2.setMchNo(mchNo);
        hisAccntOnway2.setOrderNo(orderNo);
        HisAccntOnway2 hisAccntOnway2Info = baseService.selectHisAccntOnway2(hisAccntOnway2);//在途2账户总额

        Long onway2Amt = 0L;
        if(ToolUtil.isNotEmpty(hisAccntOnway2Info)){
            onway2Amt = hisAccntOnway2Info.getEventAmt();//记录的在途2金额
        }



        String accntType = withDrawAccnt.getAccntType();//账户类型
        Long beforeMchAmt = depositoryAccnt.getRemainAmt();//存管户余额（交易记录前）
        String transtionalNo = UUID.randomUUID().toString().replace("-", "").toLowerCase();//事务号
        Date transTime = new Date();
        if("1".equals(withDrawInfo.getRemark1())){//flag=1：非超额提现，不需要准备金; flag=2:非超额提现，需要准备金; flag =3:超额提现，但不需要准备金;flag=4:超额提现，需要准备金
            //更新存管户余额
            updateDepository(depositoryAccnt, amt);
        }else if("2".equals(withDrawInfo.getRemark1())){
            //记还准备金交易记录表（记一笔退款加回去准备金的记录，并记录）
            insetMchAccntChargeUp(transTime,mchNo,Math.abs(prepayAmt));//实际还准备金应该是7，但是子商户可用总余额变更后，原先的写法就不生效了
            //更新准备金账户（把扣减的准备金加回去）
            updatePrepay(prepayAccnt,Math.abs(prepayAmt));
            //记准备金交易记录表（记一笔退款加回去准备金的记录）
            insertHisPrepay(transTime, mchNo, orderNo, Math.abs(prepayAmt), beforePrepayAmt,"refund");
            //更新存管户余额（增加准备金过来的钱，减去提现的钱）//分支
            updateDepository(depositoryAccnt, amt-Math.abs(prepayAmt));
        }else if("3".equals(withDrawInfo.getRemark1())){
            //在途2记录一笔超额提现退回记录
//            insertMchAccntOnway(transTime,mchNo,orderNo,Math.abs(onway2Amt),onway2Accnt.getBalance(),Integer.parseInt(withDrawInfo.getRemark1()));
//            //更改在途2账户（把记录的在途2的明细退回去）
//            updateOnway2(mchNo,Math.abs(onway2Amt));
            //更新存管户月（减去提现的钱）
            updateDepository(depositoryAccnt, amt);
        }else if ("4".equals(withDrawInfo.getRemark1())){
            //在途2记录超额提现记录
//            insertMchAccntOnway(transTime,mchNo,orderNo,Math.abs(onway2Amt),onway2Accnt.getBalance(),Integer.parseInt(withDrawInfo.getRemark1()));
//            //更新在途2账户余额
//            updateOnway2(mchNo,Math.abs(onway2Amt));
            //记还准备金交易记录表
            insetMchAccntChargeUp(transTime,mchNo, Math.abs(prepayAmt));
            //记录准备金交易记录明细表
            insertHisPrepay(transTime, mchNo, orderNo, Math.abs(prepayAmt), beforePrepayAmt,"refund");
            //减少准备金余额
            updatePrepay(prepayAccnt,Math.abs(prepayAmt));
            //更新存管户余额（把扣除的钱加回去，提现金额-扣除的准备金）
            updateDepository(depositoryAccnt, amt-Math.abs(prepayAmt));
        }
//                int afterDepositortAmt = (int)(Double.valueOf(depositoryAccnt.getRemain_amt())-amt);
        //更新提现账户
        Long transAmt = 0L;
        if(onway2Amt!=0){
            transAmt = Math.abs(onway2Amt);
        }
        withDrawAccnt.setRemainAmt(amt - transAmt);
        withDrawAccnt.setUpdateTime(new DateTime());
        baseService.updateMchAmtNoZero(withDrawAccnt);
        //更新商户可用总余额
        if(prepayAmt!=0){
            transAmt = Math.abs(prepayAmt);
        }
        countAmtAccnt.setRemainAmt(amt - transAmt);
        countAmtAccnt.setUpdateTime(new DateTime());
        baseService.updateMchAmtNoZero(countAmtAccnt);
        //插入存管户历史交易明细数据
        insertHisMch(transTime,transtionalNo,mchNo,orderNo,Math.abs(depositoryAccnt.getRemainAmt()),beforeMchAmt,beforeMchAmt+Math.abs(depositoryAccnt.getRemainAmt()),PayConstant.DEPOSIT_TRAN_WITHDRAW_REFUND);
        //插入提现账户历史交易明细数据
        insertWithdrawAccnt(transTime,transtionalNo,accntType,mchNo,mchAccntNo,orderNo,amt,beforeWithDrawAmt,beforeWithDrawAmt+amt,PayConstant.DEPOSIT_TRAN_WITHDRAW_REFUND);
        //如果提现时包含手续费，则需要将提现手续费退还

        if(0L!=withDrawInfo.getTransFee()){
            if("1".equals(withDrawInfo.getRemark1()) || "3".equals(withDrawInfo.getRemark1())){
                updateDepository(depositoryAccnt, withDrawInfo.getTransFee());
            }else if("2".equals(withDrawInfo.getRemark1()) || "4".equals(withDrawInfo.getRemark1())){

                insetMchAccntChargeUp(transTime, mchNo, Math.abs(prepayAmt2));

                //更新准备金账户（把扣减的准备金加回去）
                updatePrepay(prepayAccnt, Math.abs(prepayAmt2));

                //记准备金交易记录表（记一笔退款加回去准备金的记录）
                insertHisPrepay(transTime, mchNo, orderNo, Math.abs(prepayAmt2), Math.abs(prepayAmt)+beforePrepayAmt, "refund_poundage");

                //更新存管户余额（增加准备金过来的钱，减去提现的钱）//分支
                updateDepository(depositoryAccnt, withDrawInfo.getTransFee() - Math.abs(prepayAmt2));

            }

            /*//如果需要扣除手续费，则将手续费增加到分润账户中
            if(flag == 2 || flag ==4){
                insetMchAccntChargeUp(transTime, mchNo, -(long) fixedPoundage);
                updatePrepay(prepayAccnt, -(long) fixedPoundage);
                insertHisPrepay(transTime, mchNo, orderNo, -(long) fixedPoundage, beforePrepayAmt -Math.abs(amt - accntCount), "poundage");
                updateDepository(depositoryAccnt, -accntCount);
            }else if(flag == 1 || flag ==3){
                updateDepository(depositoryAccnt, -(long) fixedPoundage);
            }
            //插入存管户历史交易明细数据
            insertHisMch(transTime, transtionalNo, mchNo, orderNo, -Math.abs(depositoryAccnt.getRemainAmt()), beforeMchAmt - Math.abs(depositoryAccnt.getRemainAmt()), beforeMchAmt - Math.abs(depositoryAccnt.getRemainAmt()) -Math.abs(depositoryAccnt.getRemainAmt()) , "poundage");
            */
            long fixedPoundage = withDrawInfo.getTransFee();
            //如果需要扣除手续费，则将手续费增加到分润账户中
            insertHisMch(transTime, transtionalNo, mchNo, orderNo, fixedPoundage, beforeWithDrawAmt + amt, beforeWithDrawAmt + amt+fixedPoundage , "refund_poundage");

            //更改分润账户余额
            updateMchAccnt(mchNo, -fixedPoundage);
            MchAccnt profitAccnt = queryMchAccntByMchNo(mchNo,PayConstant.DEPOSIT_PROFIT);
            //记录分润账户明细
            insertHisMchProfit(transtionalNo, orderNo,"refund_poundage" ,mchNo, profitAccnt.getRemainAmt(),  -fixedPoundage, profitAccnt.getRemainAmt()-fixedPoundage,transTime);
            //更新提现账户
            withDrawAccnt.setRemainAmt(fixedPoundage);
            withDrawAccnt.setUpdateTime(new DateTime());
            baseService.updateMchAmtNoZero(withDrawAccnt);
            //插入提现账户历史交易明细数据
            insertWithdrawAccnt(transTime, transtionalNo, accntType, mchNo, mchAccntNo, orderNo, fixedPoundage, beforeWithDrawAmt + amt, beforeWithDrawAmt + amt + fixedPoundage, "refund_poundage");
        }
        //插入提现记录表
//        insertWithdrawInfo(transtionalNo,outoderNo,cardNo, mchNo,mchAccntNo,orderNo, amt,beforeWithDrawAmt+amt,Integer.parseInt(withDrawInfo.getRemark1()));

    }

    /**
     * 根据电商平台号，账户号查询子商户账户信息
     * <p>
     * param mchNo
     * param mchAccntNo
     * return
     */
    private MchAccnt queryMchAccntByMchNo(String mchNo, String accntType) {
        MchAccnt mchAccnt = new MchAccnt( );
        MchAccnt mchAccntBefore = null;
        mchAccnt.setAccntType(accntType);//账户号
        mchAccnt.setMchNo(mchNo);
        List<MchAccnt> mchAccntList = mchAccntMapper.selectMchAccnt(mchAccnt);//根据账户号商户号，查询账户信息
        if (ToolUtil.isNotEmpty(mchAccntList)) {
            mchAccntBefore = mchAccntList.get(0);
        }
        return mchAccntBefore;
    }


    /**
     * 插入分润账户资金明细数据
     * <p>
     * param accnt
     * param mchNo
     * param amt
     * param afertAmt
     * return
     */
    public int insertHisMchProfit(String transcationNo, String orderNo,String event,String mchNo, Long amt, Long amount, Long afertAmt,Date date) {
        //插入分润商户账户资金明细表
        HisAccntProfile hisAccntProfile = new HisAccntProfile( );
        hisAccntProfile.setMchNo(mchNo);
        hisAccntProfile.setOrderNo(orderNo);//订单号
        hisAccntProfile.setTransactionNo(transcationNo);//事务号
        hisAccntProfile.setEvent(event);//事件名称
        hisAccntProfile.setEventAmt(amount);//事件金额
        hisAccntProfile.setEventTime(date);//事件时间
        hisAccntProfile.setAccntAmtBefore(amt);//事件发生前余额
        hisAccntProfile.setAccntAmtAfter(afertAmt);//事件发生后金额
        hisAccntProfile.setCreateTime(date);//创建时间
        return baseService.insertHisProfile(hisAccntProfile);
    }
    /**
     * 更新分润账户信息
     * <p>
     * param
     * param
     * return
     */
    private int updateMchAccnt(String mchNo,  Long amount) {
        MchAccnt mchAccntBefore = new MchAccnt();
        mchAccntBefore.setMchNo(mchNo);
        mchAccntBefore.setAccntType(PayConstant.DEPOSIT_PROFIT);
        mchAccntBefore.setRemainAmt(amount);
        mchAccntBefore.setUpdateTime(new DateTime( ));
        return baseService.updateMchAmtNoZero(mchAccntBefore);
    }

    /**
     * 更新存管户账户信息
     * @param depositoryAccnt
     * @param amt
     * @return
     */
    private int updateDepository(MchAccnt depositoryAccnt,Long amt ){
        depositoryAccnt.setRemainAmt(amt);//存管户账户余额减掉
        depositoryAccnt.setUpdateTime(new DateTime());
        return baseService.updateMchAmt(depositoryAccnt);
    }

    /**
     * 更新准备金
     * @param prepayAccnt
     * @param amt
     */
    private void updatePrepay(MchAccnt prepayAccnt,Long amt){
        prepayAccnt.setRemainAmt(amt);
        prepayAccnt.setUpdateTime(new DateTime());
        baseService.updateMchAmt(prepayAccnt);
    }

    /**
     * 更新在途2账户余额
     * @param mchNo
     * @param amt
     */
    private void updateOnway2(String mchNo,Long amt){
        MchAccnt mchAccnt = new MchAccnt();
        mchAccnt.setMchNo(mchNo);
        mchAccnt.setAccntType("onway2");
        mchAccnt.setRemainAmt(-amt);
        baseService.updateMchAmtNoZero(mchAccnt);
    }

    /**
     * 记录在途2交易明细，更新在途2交易明细总额
     * @param mchNo 商户号
     * @param orderNo 订单号  标识提现
     * @param eventAmt 事件金额
     * @param beforeAmt 事件前金额
     * @param flag
     */
    public void  insertMchAccntOnway(Date transTime,String mchNo,String orderNo,Long eventAmt,Long beforeAmt,int flag){

        HisAccntOnway2 hisAccntOnway2 = new HisAccntOnway2();
        hisAccntOnway2.setMchNo(mchNo);//商户号
        hisAccntOnway2.setOrderNo(orderNo);//订单号
        hisAccntOnway2.setTransactionNo("");//事务号
        hisAccntOnway2.setEvent("withdraw");//
        hisAccntOnway2.setEventAmt(eventAmt);//事件金额(超出提现账户可用余额部分)
        hisAccntOnway2.setEventTime(transTime);
        hisAccntOnway2.setAccntAmtBefore(beforeAmt);//事件发生前余额
        if(flag ==4){
            hisAccntOnway2.setFlag("1");
        }else {
            hisAccntOnway2.setFlag("0");
        }
        hisAccntOnway2.setAccntAmtAfter(beforeAmt+hisAccntOnway2.getEventAmt());//事件发生后金额
        hisAccntOnway2.setCreateTime(new DateTime());
        hisAccntOnway2.setType("detailed");
        baseService.insertHisAccntOnway2(hisAccntOnway2);

        HisAccntOnway2 hisAccntOnway21 =  new HisAccntOnway2();
        hisAccntOnway21.setBalance(hisAccntOnway2.getAccntAmtAfter());
        hisAccntOnway21.setType("count");
        hisAccntOnway21.setMchNo(mchNo);
        baseService.updateHisAccntOnway2(hisAccntOnway21);


    }

    /**
     * 记录还准备金记录表，更新还准备金明细总额
     * @param mchNo 商户号
     * @param chargeUpAmt 事件金额
     */
    public void insetMchAccntChargeUp(Date transTime,String mchNo,Long chargeUpAmt){
        MchAccntChargeUp mchAccntChargeUp = new MchAccntChargeUp();
        mchAccntChargeUp.setMchNo(mchNo);//商户号
        mchAccntChargeUp.setAccntTypeLender("prepay");//出借方
        mchAccntChargeUp.setAccntTypeBorrower("depository");//借方
        mchAccntChargeUp.setChargeUpTime(transTime);//挂账时间
        mchAccntChargeUp.setIdDepositTransaction("");//事务号
        mchAccntChargeUp.setStatu("0");//挂账状态
        mchAccntChargeUp.setChargeUpAmt(chargeUpAmt);
        mchAccntChargeUp.setType("detailed");//挂账类型（明细）
        baseService.insertMchAccntChargeUp(mchAccntChargeUp);

        MchAccntChargeUp mchAccntChargeUp1 = new MchAccntChargeUp();
        mchAccntChargeUp1.setMchNo(mchNo);
        mchAccntChargeUp1.setType("count");
        mchAccntChargeUp1.setBalance(mchAccntChargeUp.getChargeUpAmt());
        mchAccntChargeUp1.setUpdateTime(new DateTime());
        baseService.updateMchAcchtChargeUpAmt(mchAccntChargeUp1);
    }

    /**
     * 记录准备金历史交易明细
     * @param mchNo 商户号
     * @param orderNo 订单号
     * @param eventAmt  事件金额
     * @param beforePrepayAmt
     */
    public void  insertHisPrepay(Date transTime,String mchNo,String orderNo,Long eventAmt,Long beforePrepayAmt,String event) {

        HisAccntPrepay hisAccntPrepay = new HisAccntPrepay();
        hisAccntPrepay.setMchNo(mchNo);//商户号
        hisAccntPrepay.setOrderNo(orderNo);//订单号
        hisAccntPrepay.setTransactionNo("");//事务号
        hisAccntPrepay.setEvent(event);//
        hisAccntPrepay.setEventAmt(eventAmt);//事件金额(超出提现账户可用余额部分)
        hisAccntPrepay.setEventTime(transTime);
        hisAccntPrepay.setAccntAmtBefore(beforePrepayAmt);//事件发生前余额
        hisAccntPrepay.setAccntAmtAfter(beforePrepayAmt + hisAccntPrepay.getEventAmt());//事件发生后金额
        hisAccntPrepay.setCreateTime(new DateTime());
        baseService.insertHisPrepay(hisAccntPrepay);
    }




    /**
     * 插入存管户历史资金交易明细表
     * @param mchNo 电商平台号
     * @param orderNo 订单号
     * @param amt 提现金额
     * @param beforeMchAmt 提现前余额
     * @return
     */
    private int insertHisMch(Date transTime,String transtionalNo,String mchNo,String orderNo,Long amt,Long beforeMchAmt,Long afterMchAmt,String event){
        //更新存管户历史记录表
        HisAccntMch hisMchAccnt = new HisAccntMch();
        hisMchAccnt.setMchNo(mchNo);//商户号
        hisMchAccnt.setOrderNo(orderNo);//订单号
        hisMchAccnt.setTransactionNo(transtionalNo);//事务号
        hisMchAccnt.setEvent(event);//事件名称
        hisMchAccnt.setEventAmt(amt);//事件金额
        hisMchAccnt.setEventTime(transTime);
        hisMchAccnt.setAccntAmtBefore(beforeMchAmt);//事件发生前余额
        hisMchAccnt.setAccntAmtAfter(afterMchAmt);//事件发生后金额
        hisMchAccnt.setCreateTime(new DateTime());
        return baseService.insertHisMchAccnt(hisMchAccnt);
    }

    /**
     * 插入提现账户历史资金交易明细表
     * @param transtionalNo
     * @param accntType
     * @param mchNo
     * @param mchAccntNo
     * @param orderNo
     * @param amt
     * @param beforeWithDrawAmt
     * @param afterAmt
     * @return
     */
    private int  insertWithdrawAccnt(Date transTime,String transtionalNo,String accntType,String mchNo,String mchAccntNo,String orderNo,Long amt,Long beforeWithDrawAmt,Long afterAmt,String event){
        if("mchsub".equals(accntType)){
            HisAccntMchSub hisAccntMchSub = new HisAccntMchSub();
            hisAccntMchSub.setMchNo(mchNo);//商户号
            hisAccntMchSub.setMchAccntNo(mchAccntNo);//子商户账户号
            hisAccntMchSub.setOrderNo(orderNo);//订单号
            hisAccntMchSub.setTransactionNo(transtionalNo);//事务号
            hisAccntMchSub.setEvent(event);//事件名称
            hisAccntMchSub.setEventAmt(amt);//事件金额
            hisAccntMchSub.setEventTime(transTime);//事件时间
            hisAccntMchSub.setAccntAmtBefore(beforeWithDrawAmt);//事件发生前余额
            hisAccntMchSub.setAccntAmtAfter(afterAmt);//事件发生后金额
            hisAccntMchSub.setCreateTime(new DateTime());//创建时间
            return baseService.insertHisMchASub(hisAccntMchSub);
        }if("profit".equals(accntType)){
            HisAccntProfile hisAccntProfile = new HisAccntProfile();
            hisAccntProfile.setMchNo(mchNo);
            hisAccntProfile.setOrderNo(orderNo);//订单号
            hisAccntProfile.setTransactionNo(transtionalNo);//事务号
            hisAccntProfile.setEvent(event);//事件名称
            hisAccntProfile.setEventAmt(amt);//事件金额
            hisAccntProfile.setEventTime(transTime);//事件时间
            hisAccntProfile.setAccntAmtBefore(beforeWithDrawAmt);//事件发生前余额
            hisAccntProfile.setAccntAmtAfter(afterAmt);//事件发生后金额
            hisAccntProfile.setCreateTime(new DateTime());//创建时间
            return baseService.insertHisProfile(hisAccntProfile);
        }
        return 0;
    }
}
